package com.jincheng.system.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.jincheng.common.core.domain.entity.SysRole;
import com.jincheng.common.exception.ServiceException;
import com.jincheng.common.utils.DateUtils;
import com.jincheng.system.domain.Activity;
import com.jincheng.system.domain.SignInSheet;
import com.jincheng.system.domain.Tribe;
import com.jincheng.system.domain.dto.SignInSheetScreenDTO;
import com.jincheng.system.domain.dto.SignInSheetSimpleDTO;
import com.jincheng.system.mapper.ActivityMapper;
import com.jincheng.system.mapper.SignInSheetMapper;
import com.jincheng.system.mapper.TribeMapper;
import com.jincheng.system.service.ISignInSheetService;
import com.jincheng.system.service.ISysNoticeService;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

import static com.jincheng.common.utils.PageUtils.startPage;
import static com.jincheng.common.utils.SecurityUtils.*;

/**
 * 签到记录Service业务层处理
 *
 * @author DairyJay
 * @date 2025-02-24
 */
@Service
public class SignInSheetServiceImpl implements ISignInSheetService {
    private final SignInSheetMapper signInSheetMapper;
    private final ActivityMapper activityMapper;
    private final ISysNoticeService noticeService;
    private final TribeMapper tribeMapper;

    public SignInSheetServiceImpl(SignInSheetMapper signInSheetMapper,
                                  ActivityMapper activityMapper,
                                  ISysNoticeService noticeService,
                                  TribeMapper tribeMapper) {
        this.signInSheetMapper = signInSheetMapper;
        this.activityMapper = activityMapper;
        this.noticeService = noticeService;
        this.tribeMapper = tribeMapper;
    }

    /**
     * 查询签到记录
     *
     * @param checkInId 签到记录主键
     * @return 签到记录
     */
    @Override
    public SignInSheet selectSignInSheetByCheckInId(Long checkInId) {
        return signInSheetMapper.selectById(checkInId);
    }

    /**
     * 查询签到记录列表
     *
     * @param signInSheet 签到记录
     * @return 签到记录
     */
    @Override
    public List<SignInSheet> selectList(SignInSheet signInSheet) {
        LambdaQueryWrapper<SignInSheet> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper
                .eq(signInSheet.getCheckInId() != null,
                        SignInSheet::getCheckInId, signInSheet.getCheckInId())
                .eq(signInSheet.getActivityId() != null,
                        SignInSheet::getActivityId, signInSheet.getActivityId())
                .eq(signInSheet.getUserId() != null,
                        SignInSheet::getUserId, signInSheet.getUserId())
                .eq(signInSheet.getAuditStatus() != null,
                        SignInSheet::getAuditStatus, signInSheet.getAuditStatus())
                .eq(signInSheet.getSignInType() != null,
                        SignInSheet::getSignInType, signInSheet.getSignInType());
        return signInSheetMapper.selectList(queryWrapper);
    }

    /**
     * 根据活动id查询报名信息
     *
     * @param signInSheetScreenDTO 筛选信息
     * @return 报名信息
     */
    @Override
    public List<SignInSheetSimpleDTO> selectSignInSheetByActivityId(SignInSheetScreenDTO signInSheetScreenDTO) {
        Activity activity = activityMapper.selectActivityByActivityId(signInSheetScreenDTO.getActivityId());
        Tribe tribe = tribeMapper.selectById(activity.getTribeId());
        List<SysRole> roles = getLoginUser().getUser().getRoles();
        boolean isAdmin = false;
        for (SysRole role : roles)
            if (Objects.equals(role.getRoleKey(), "admin") || Objects.equals(role.getRoleKey(), "manage")) {
                isAdmin = true;
                break;
            }
        if (!isAdmin && !Objects.equals(tribe.getChairId(), getUserId()))
            throw new ServiceException("只能查看自己负责活动的报名信息！");
        startPage();
        return signInSheetMapper.selectSignInSheetListByActivityId(signInSheetScreenDTO);
    }

    /**
     * 获取报名人数统计信息
     *
     * @param activityId 活动id
     * @return 报名人数统计信息
     */
    @Override
    public Map<String, Object> peopleCounting(Long activityId) {
        Map<String, Object> data = new HashMap<>();

        // 获取报名信息
        SignInSheet signInSheet = new SignInSheet();
        signInSheet.setActivityId(activityId);
        signInSheet.setAuditStatus(0);
        List<SignInSheet> signInSheetList = selectList(signInSheet);

        // 获取报名人数
        Map<String, Long> participantCounts = getActivityParticipantCounts(signInSheetList);
        data.put("signNum", buildSignNum(participantCounts));

        // 处理签到员信息
        if (!signInSheetList.isEmpty()) {
            data.put("signInClerk", getSignInClerkIds(signInSheetList));
        }

        return data;
    }

    /**
     * 新增签到记录
     *
     * @param signInSheet 签到记录
     * @return 结果
     */
    @Override
    public int insertSignInSheet(SignInSheet signInSheet) {
        // 设置更新时间
        signInSheet.setUpdateTime(DateUtils.getNowDate());
        signInSheet.setUpdateBy(getUsername());

        LambdaQueryWrapper<SignInSheet> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper
                .eq(SignInSheet::getActivityId, signInSheet.getActivityId())
                .eq(SignInSheet::getUserId, signInSheet.getUserId());

        int affectedRows;
        if (signInSheetMapper.selectCount(queryWrapper) > 0) {
            affectedRows = signInSheetMapper.update(signInSheet, queryWrapper);
        } else {
            // 设置添加时间
            signInSheet.setCreateTime(DateUtils.getNowDate());
            signInSheet.setCreateBy(getUsername());
            affectedRows = signInSheetMapper.insert(signInSheet);
        }

        return affectedRows;
    }

    /**
     * 修改签到记录
     *
     * @param signInSheet 签到记录
     * @return 结果
     */
    @Override
    public int updateSignInSheet(SignInSheet signInSheet) {
        signInSheet.setUpdateTime(DateUtils.getNowDate());
        return signInSheetMapper.updateSignInSheet(signInSheet);
    }

    /**
     * 批量删除签到记录
     *
     * @param checkInIds 需要删除的签到记录主键
     * @return 结果
     */
    @Override
    public int deleteSignInSheetByCheckInIds(Long[] checkInIds) {
        return signInSheetMapper.deleteSignInSheetByCheckInIds(checkInIds);
    }

    /**
     * 删除签到记录信息
     *
     * @param checkInId 签到记录主键
     * @return 结果
     */
    @Override
    public int deleteSignInSheetByCheckInId(Long checkInId) {
        return signInSheetMapper.deleteSignInSheetByCheckInId(checkInId);
    }

    /**
     * 判断用户是否已经报名
     *
     * @param activityId 活动ID
     * @param userId     用户id
     * @return 是否报名
     */
    @Override
    public boolean checkWhetherApply(Long activityId, Long userId) {
        LambdaQueryWrapper<SignInSheet> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper
                .eq(SignInSheet::getActivityId, activityId)
                .eq(SignInSheet::getUserId, userId)
                .ne(SignInSheet::getAuditStatus, 3);
        return signInSheetMapper.selectCount(queryWrapper) > 0;
//        return signInSheetMapper.checkWhetherApply(activityId, userId) > 0;
    }

    /**
     * 插入报名信息
     *
     * @param activityId 活动id
     * @param userId     用户id
     * @return 是否报名成功
     */
    @Override
    public boolean insertApplyInfo(Long activityId, Long userId, Integer auditStatus) {
        SignInSheet signInSheet = new SignInSheet();
        signInSheet.setActivityId(activityId);
        signInSheet.setUserId(userId);
        signInSheet.setAuditStatus(auditStatus);

        return insertSignInSheet(signInSheet) > 0;
    }


    @Override
    public SignInSheet selectSignInSheetByActivityUser(Long userId, Long activityId) {
        SignInSheet signInSheet = new SignInSheet();
        signInSheet.setActivityId(activityId);
        signInSheet.setUserId(userId);
        List<SignInSheet> signInSheetList = selectList(signInSheet);
        if (!signInSheetList.isEmpty()) {
            return signInSheetList.get(0);
        }
        return null;
    }

    /**
     * 批量更改报名状态
     *
     * @param signInSheetIdList 报名信息集合
     * @param status            状态
     * @return 结果
     */
    @Override
    public int updateSignInSheetCheckStatus(List<SignInSheet> signInSheetIdList, Integer status) {
        Long activityId = signInSheetIdList.get(0).getActivityId();
        Activity activity = activityMapper.selectActivityByActivityId(activityId);

        LambdaUpdateWrapper<SignInSheet> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(SignInSheet::getActivityId, activityId);
        List<Long> signInSheetIds = signInSheetIdList.stream()
                .map(SignInSheet::getCheckInId)
                .toList();

        updateWrapper.in(SignInSheet::getCheckInId, signInSheetIds);

        updateWrapper.set(SignInSheet::getAuditStatus, status);
        updateWrapper.set(SignInSheet::getUpdateBy, getUsername());
        updateWrapper.set(SignInSheet::getUpdateTime, DateUtils.getNowDate());

        int total = signInSheetMapper.update(updateWrapper);

        if (total > 0) {
            if (status == 0) {
                List<Long> userIdList = signInSheetIdList.stream()
                        .map(SignInSheet::getUserId)
                        .toList();
                noticeService.sendActivityApplyPassNotice(activity, userIdList);
            } else if (status == 1) {
                List<Long> userIdList = signInSheetIdList.stream()
                        .map(SignInSheet::getUserId)
                        .toList();
                noticeService.sendActivityApplyFailNotice(activity, userIdList);
            }
        }
        return total;
    }

    /**
     * 获取活动相关人数（报名、签到、签退）
     *
     * @param signInSheetList 签到表数据列表
     * @return 包含报名、签到、签退人数的 Map
     */
    private Map<String, Long> getActivityParticipantCounts(List<SignInSheet> signInSheetList) {
        Map<String, Long> counts = new HashMap<>();
        long signUpCount = signInSheetList.size();
        counts.put("signUpCount", signUpCount);

        long signInCount = signInSheetList.stream()
                .filter(sheet -> sheet.getSignInTime() != null)
                .count();
        counts.put("signInCount", signInCount);

        long signOutCount = signInSheetList.stream()
                .filter(sheet -> sheet.getSignOutTime() != null)
                .count();
        counts.put("signOutCount", signOutCount);

        return counts;
    }

    /**
     * 根据活动人数构造 signNum 列表
     *
     * @param counts 包含报名、签到、签退人数的 Map
     * @return signNum 列表
     */
    private List<Map<String, Object>> buildSignNum(Map<String, Long> counts) {
        List<Map<String, Object>> signNum = new ArrayList<>();
        signNum.add(createSignNumEntry("已报名人数", counts.getOrDefault("signUpCount", 0L)));
        signNum.add(createSignNumEntry("已签到人数", counts.getOrDefault("signInCount", 0L)));

        if (counts.containsKey("signOutCount")) {
            signNum.add(createSignNumEntry("已签退人数", counts.getOrDefault("signOutCount", 0L)));
        }

        return signNum;
    }

    /**
     * 辅助方法：创建签到人数条目
     *
     * @param title  标题
     * @param number 数量
     * @return 包含标题和数量的 Map
     */
    private Map<String, Object> createSignNumEntry(String title, long number) {
        Map<String, Object> entry = new HashMap<>();
        entry.put("title", title);
        entry.put("number", number);
        return entry;
    }

    /**
     * 获取签到员ID列表
     *
     * @param signInSheetList 签到表数据列表
     * @return 签到员ID列表
     */
    private List<Long> getSignInClerkIds(List<SignInSheet> signInSheetList) {
        return signInSheetList.stream()
                .filter(sheet -> sheet.getPosition() == 2)
                .map(SignInSheet::getUserId)
                .collect(Collectors.toList());
    }


}

